package com.mtable.base;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.mtable.entity.MMenu;
import com.mtable.entity.MUser;
@Service
public class BaseServiceImpl<T> implements BaseService<T> {
	
	private Class<T> classType;
	
	@Autowired
	public BaseServiceImpl(BaseDao<T> basedao){
		this.baseDao = basedao;
		Type type = basedao.getClass().getGenericSuperclass();
		if (type instanceof ParameterizedType) {
			ParameterizedType pt = (ParameterizedType) type;
			classType = (Class) pt.getActualTypeArguments()[0];
		}
	}

	protected BaseDao<T> baseDao;
	
	@Override
	public void delete(T t) {
		baseDao.delete(t);
	}

	@Override
	public List<T> findAll() {
		return baseDao.findAll();
	}

	@Override
	public T findById(Integer id) {
		return baseDao.findById(id);
	}

	@Override
	public List<T> findByProperty(String propertyName, Object value) {
		return baseDao.findByProperty(propertyName, value);
	}

	@Override
	public T merge(T t) {
		return baseDao.merge(t);
	}

	@Override
	public void save(T t) {
		baseDao.save(t);
	}
	
	private String getPackageEntityName(){
		return classType.getName();
	}
	private String getEntityName(){
		String eName = classType.getName();
		return  eName.substring(eName.lastIndexOf(".")+1);
	}
	
	@Override
	public List<T> query(HttpServletRequest request,HttpServletResponse response){
		String queryStr = request.getQueryString();
		/**The resulting request to the server would be:
		/FooObject/?foo=value1&sortBy=+foo,-bar
	If sortParam is not set, the sort value is appended without a key-value pair, surrounded by "sort()":
		/FooObject/?foo=value1&sort(+foo,-bar)
	*/
		//hql
		StringBuilder hql = new StringBuilder(); 
		hql.append("from ").append(this.getEntityName()).append(" as ").append(this.getEntityName().toLowerCase());
		
		//1. 插入 条件字符串
		appendHqlConditionStr(hql,queryStr);
		//2. 插入 排序字符串
		appendHqlSortStr(hql,queryStr);
		//3. 分页参数
		String queryRange = request.getHeader("Range");
		List<T> list = null;
		if(queryRange == null){
			list = this.baseDao.query(hql.toString());
		}else{
			int firstIndex,maxSize,pageNo,pageSize;
			if(queryRange.length()>=6 && queryRange.substring(6).split("-").length == 2){
				String[] indexArr = queryRange.substring(6).split("-");
				firstIndex = Integer.parseInt(indexArr[0]);
				int endIndex = Integer.parseInt(indexArr[1]);
				pageSize = maxSize = endIndex - firstIndex +1;
				pageNo = firstIndex / pageSize +1;
				list = this.baseDao.query(hql.toString(), pageNo, pageSize);
				int count = baseDao.countQuery(hql.toString());
				//server side return header: Content-Range: items 0-24/66
				response.setHeader("Content-Range", "items " + firstIndex+"-"+(firstIndex+pageSize)+"/"+count);
			}else{
				firstIndex = 0;
				pageSize = maxSize = 0;
				pageNo=0;
				list = this.baseDao.query(hql.toString());
			}
		}
		response.setCharacterEncoding("UTF-8");
		return list;
		//client Range header: Range: items=0-24
		//server side return header: Content-Range: items 0-24/66
		/**The resulting request to the server would be:
			/FooObject/?foo=value1&sortBy=+foo,-bar
		If sortParam is not set, the sort value is appended without a key-value pair, surrounded by "sort()":
			/FooObject/?foo=value1&sort(+foo,-bar)
		*/
	}
	/**
	 * 往hql 中加入 条件字符串
	 * @param hql
	 * @param queryStr
	 * @return
	 */
	public StringBuilder appendHqlConditionStr(StringBuilder hql,String queryStr){
		if(queryStr == null){
			return hql;
		}
		//queryStr foo=value1&sortBy=+foo,-bar
		int sortByIndex = queryStr.indexOf("sortBy");
		int sortIndex = queryStr.indexOf("sort(");
		String conditionStr = new String();
		if(sortByIndex > 0){
			//有排序
			conditionStr = queryStr.substring(0, sortByIndex-2);
		}else if(sortIndex > 0){
			//无排序
			conditionStr = queryStr.substring(0, sortIndex-2);
		}else{
			return hql;
		}
		//有条件字符串需要 拼
		hql.append(" where ");
		String entityName = getEntityName().toLowerCase();
		//多个
		if(conditionStr.indexOf("&")>=0){
			String[] condiP = conditionStr.split("&");
			for(String cond : condiP){
				hql.append(entityName).append(".").append(cond).append(" and ");
			}
		}else{
			hql.append(entityName).append(".").append(conditionStr).append(" and ");
		}
		hql.substring(0, hql.length()-4);
		return hql;
	}
	
	/**
	 * 往hql 中加入 排序字符串
	 * @param hql
	 * @param queryStr
	 * @return
	 */
	public StringBuilder appendHqlSortStr(StringBuilder hql,String queryStr){
		if(queryStr == null){
			return hql;
		}
		//queryStr foo=value1&sortBy=+foo,-bar
		int sortByIndex = queryStr.indexOf("sortBy");
		if(sortByIndex ==-1){
			return hql;
		}
		//有排序字符串需要 拼
		String entityName = getEntityName().toLowerCase();
		hql.append(" order by ");
		String sortStr = queryStr.substring(queryStr.indexOf("sortBy")+7);//+foo,-bar
		if(sortStr.indexOf(",") > 0){
			String[] sortArr = sortStr.split(",");
			for(String sort : sortArr){
				hql.append(entityName).append(".").append(sort.substring(1))
					.append(sort.charAt(0)=='+'?" asc,":" desc,");
			}
		}else{
			hql.append(entityName).append(".").append(sortStr.substring(1))
			.append(sortStr.charAt(0)=='+'?" asc,":" desc,");
		}
		hql.deleteCharAt(hql.length()-1);
		return hql;
	}
	
	/**
	 * 返回一个 数组json字符串
	 * @param list
	 * @return
	 */
	public String generateJsonArray(List<T> list){
		JSONObject jobj;
		JSONArray jarry = new JSONArray();
		for(T t : list){
			jobj = new JSONObject(t);
			jarry.put(jobj);
		}
		return jarry.toString();
	}
	
}
